package cn.xqj.basic.service.impl;

import cn.xqj.basic.dto.SmsDto;
import cn.xqj.basic.exception.BusinessException;
import cn.xqj.basic.service.IVerifyCodeService;
import cn.xqj.basic.util.AjaxResult;
import cn.xqj.basic.util.SmsUtil;
import cn.xqj.basic.util.StrUtils;
import cn.xqj.user.domain.User;
import cn.xqj.user.mapper.UserMapper;
import com.wf.captcha.ArithmeticCaptcha;
import org.apache.poi.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class VerifyCodeServiceImpl implements IVerifyCodeService {


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;


    @Override
    @Transactional
    public AjaxResult captcha() {
        // SpecCaptcha specCaptcha = new SpecCaptcha(115, 42, 5);
        ArithmeticCaptcha specCaptcha = new ArithmeticCaptcha(115, 42);
        String verCode = specCaptcha.text().toLowerCase();
        System.out.println(verCode);
        String key = UUID.randomUUID().toString();
        System.out.println(key);
        // 存入redis并设置过期时间为5分钟

        redisTemplate.opsForValue().set(key, verCode, 5, TimeUnit.MINUTES);

        // 将key和base64返回给前端
        Map map = new HashMap<>();
        map.put("key", key);
        map.put("image", specCaptcha.toBase64());
        return AjaxResult.me().setResultObj(map);
    }

    @Override
    @Transactional
    public void smsCode(SmsDto smsDto) {
        // 获取前端参数
        // 前端输入的电话号码
        String phone = smsDto.getPhone();
        // 前端输入的 图片验证码
        String imageCode = smsDto.getImageCode();
        // 前端传递的图片验证码的key（redis中）
        String imageCodeKey = smsDto.getImageCodeKey();

        // 非空校验
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("电话号码不能为空！");
        }
        // 非空校验
        if (StringUtils.isEmpty(imageCode)) {
            throw new BusinessException("图形验证码不能为空！");
        }
        // 非空校验
        if (StringUtils.isEmpty(imageCodeKey)) {
            throw new BusinessException("图形验证码key不能为空！");
        }


        Object redisImageCode = redisTemplate.opsForValue().get(imageCodeKey);
        if (redisImageCode == null) {
            throw new BusinessException("图形验证码已过期！请刷新后重试！");
        }

        if (!imageCode.equalsIgnoreCase(redisImageCode.toString())) {
            throw new BusinessException("图形验证码输入错误！请重试！");
        }


        // 校验当前手机号码是否注册过
        User user = userMapper.findByPhone(phone);
        if (user != null) {
            throw new BusinessException("当前手机号码已经注册，请勿重复注册！");
        }


        // 通过前端输入的的电话号码去redis中查询验证码
        Object redisSmsCode = redisTemplate.opsForValue().get("register:"+phone);
        // 申明验证码变量
        String code = null;

        // 如果redis中查询出来的结果为空时
        if (redisSmsCode == null) {
            // 就生成6位验证码 赋值给code
            code = StrUtils.getRandomString(6);
        } else {
            // 如果redis中查询出来的结果不为空时
            // 就获取存入的时间戳
            long redisTime = Long.parseLong(redisSmsCode.toString().split(":")[1]);
            // 获取当前时间戳
            long now = System.currentTimeMillis();
            // 判断如果当前时间戳  减去 存入的时间戳 时间小于60秒时 就抛异常结束方法 不让用户在1分钟内重复获取
            if ((now - redisTime) < 1*60*1000) {
                throw new BusinessException("请勿重复获取验证码");
            } else {
                // 如果时间大于等于60秒时 就让用户重新获取验证码（第一次发送的验证码  重复发送给用户）
                code = redisSmsCode.toString().split(":")[0];
            }
        }

        // 将验证码和手机号按照格式存入redis（register：手机号 ， 验证码：时间戳）
        redisTemplate.opsForValue().set("register:"+phone, code + ":" + System.currentTimeMillis(), 5, TimeUnit.MINUTES);


        // 调用工具类发送短信
        // SmsUtil.sendSms(phone,"您的验证码是："+ code + ",有效时间5分钟！");
        System.out.println(phone + "--您的验证码是："+ code + ",有效时间5分钟！");
    }

    @Override
    public void binderSmsCode(SmsDto smsDto) {
        // 获取前端参数
        // 前端输入的电话号码
        String phone = smsDto.getPhone();


        // 非空校验
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("电话号码不能为空！");
        }


        // 通过前端输入的的电话号码去redis中查询验证码
        Object redisSmsCode = redisTemplate.opsForValue().get("binder:"+phone);
        // 申明验证码变量
        String code = null;

        // 如果redis中查询出来的结果为空时
        if (redisSmsCode == null) {
            // 就生成6位验证码 赋值给code
            code = StrUtils.getRandomString(6);
        } else {
            // 如果redis中查询出来的结果不为空时
            // 就获取存入的时间戳
            long redisTime = Long.parseLong(redisSmsCode.toString().split(":")[1]);
            // 获取当前时间戳
            long now = System.currentTimeMillis();
            // 判断如果当前时间戳  减去 存入的时间戳 时间小于60秒时 就抛异常结束方法 不让用户在1分钟内重复获取
            if ((now - redisTime) < 1*60*1000) {
                throw new BusinessException("请勿重复获取验证码");
            } else {
                // 如果时间大于等于60秒时 就让用户重新获取验证码（第一次发送的验证码  重复发送给用户）
                code = redisSmsCode.toString().split(":")[0];
            }
        }

        // 将验证码和手机号按照格式存入redis（register：手机号 ， 验证码：时间戳）
        redisTemplate.opsForValue().set("binder:"+phone, code + ":" + System.currentTimeMillis(), 5, TimeUnit.MINUTES);


        // 调用工具类发送短信
        // SmsUtil.sendSms(phone,"您的验证码是："+ code + ",有效时间5分钟！");
        System.out.println(phone + "--您的验证码是："+ code + ",有效时间5分钟！");
    }
}
